﻿#region Using Declaration

using Opc.Da;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Timers;
using System.Windows.Forms;

#endregion Using Declaration

namespace T4_Eind_programma
{
    public class Controller
    {
        #region Variable Declaration

        protected static Opc.Da.Subscription group;
        protected static Opc.Da.Server m_server;
        protected Opc.Da.SubscriptionState groupStateRead = new Opc.Da.SubscriptionState();
        private const string opcnaam = "T4 PROJECT>CAL CONNECTION>";
        private List<Doeltank> doelTanken = new List<Doeltank>();

        private List<ItemInfo> itemInfoList = new List<ItemInfo>();

        private FileIO mijnIO = new FileIO();
        private BindingList<Order> orderList = new BindingList<Order>();
        private System.Timers.Timer timer = new System.Timers.Timer(1500);

        private Stopwatch totalTime = new Stopwatch();
        private Stopwatch totalTimeActive = new Stopwatch();

        #endregion Variable Declaration

        #region Properties

        public List<ItemInfo> ItemInfoList
        {
            get { return itemInfoList; }
            set { itemInfoList = value; }
        }

        public FileIO MijnIO
        {
            get { return mijnIO; }
            set { mijnIO = value; }
        }

        public BindingList<Order> OrderList
        {
            get { return orderList; }
            set { orderList = value; }
        }

        #endregion Properties

        #region Constructor

        public Controller()
        {
            MaakVerbinding();
            AanmakenTags(group);
            totalTime.Start();
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Enabled = true;
            timer.AutoReset = true;
            doelTanken.Add(new Doeltank(6));
            doelTanken.Add(new Doeltank(7));
            doelTanken.Add(new Doeltank(8));
            doelTanken.Add(new Doeltank(9));
        }

        #endregion Constructor

        #region VerbindingOPC

        public void DisconnectOPC()
        {
            if (m_server != null && m_server.IsConnected == true)
                m_server.Disconnect();
        }

        public void MaakVerbinding()
        {
            //vanuit Maakverbinding word ook de group aangemaakt, omdat deze toch maar 1 keer word aangemaakt.
            try
            {
                m_server = null;

                m_server = new Opc.Da.Server(new OpcCom.Factory(), null);

                m_server.Connect(new Opc.URL("opcda://Matrikon.OPC.SiemensPLC.1"), new Opc.ConnectData(
                    new System.Net.NetworkCredential()
                    {
                        UserName = "",
                        Password = ""
                    }));

                //na het aanmaken van de verbinding word de group aangemaakt.
                MaakGroup("Group0", 1000, true);
            }
            catch
            {
                DisconnectOPC();
                MessageBox.Show("fout met verbinden", "error", MessageBoxButtons.OK);
            }
        }

        #endregion VerbindingOPC

        #region OPC

        public void AanmakenTags(Opc.Da.Subscription group)
        {
            StreamReader reader = new StreamReader(mijnIO.Location + "aanmakentags.txt");
            List<string> tagsFromFile = new List<string>();
            while (!reader.EndOfStream)
            {
                tagsFromFile.Add(reader.ReadLine());
            }
            int aantal = tagsFromFile.Count();
            try
            {
                Opc.Da.Item[] item1 = new Opc.Da.Item[aantal];
                for (int i = 0; i < item1.Length; i++)
                {
                    item1[i] = new Opc.Da.Item() { ItemName = opcnaam + tagsFromFile[i] };
                }

                group.AddItems(item1);
            }
            catch
            {
                DisconnectOPC();
                MessageBox.Show("Fout bij aanmaken Tags", "fout", MessageBoxButtons.OK);
            }
        }

        public void GeefVeranderingenDoorAanOPCItemInfo(List<ItemInfo> newInfo)
        {
            try
            {
                group.RemoveItems(group.Items);
                List<ItemValue> valueList = new List<ItemValue>();
                Item[] itemArray = new Item[newInfo.Count];

                for (int i = 0; i < itemArray.Length; i++)
                {
                    itemArray[i] = new Item();
                    itemArray[i].ItemName = newInfo[i].Name;
                    ItemValue itemValue = new ItemValue(itemArray[i]);
                    itemValue.Value = newInfo[i].ItemValue;
                    valueList.Add(itemValue);
                }
                //#1: assign the item to the group so the items gets a ServerHandle
                group.AddItems(itemArray);
                // #2: assign the server handle to the ItemValue
                for (int i = 0; i < valueList.Count; i++)
                    valueList[i].ServerHandle = group.Items[i].ServerHandle;
                // #3: write
                group.Write(valueList.ToArray());
            }
            catch
            {
                DisconnectOPC();
                MessageBox.Show("Kan het niet weg schrijven", "error", MessageBoxButtons.OK);
            }
        }

        public void WriteMengbatchToOPC(Mengbatch mengbatch)
        {
            StreamReader reader = new StreamReader(mijnIO.Location + "writemengbatchtags.txt");
            List<string> tagsFromFile = new List<string>();
            while (!reader.EndOfStream)
            {
                tagsFromFile.Add(reader.ReadLine());
            }
            int aantal = tagsFromFile.Count();

            try
            {
                group.RemoveItems(group.Items);
                List<ItemValue> valueList = new List<ItemValue>();
                Item[] itemArray = new Item[aantal];
                for (int i = 0; i < itemArray.Length; i++)
                {
                    itemArray[i] = new Item();
                    itemArray[i].ItemName = opcnaam + tagsFromFile[i];
                    ItemValue waardeItem = new ItemValue(itemArray[i]);

                    switch (itemArray[i].ItemName)
                    {
                        case "T4 PROJECT>CAL CONNECTION>doeltank":
                            waardeItem.Value = mengbatch.Doeltank;
                            break;

                        case "T4 PROJECT>CAL CONNECTION>mengtijd":
                            waardeItem.Value = mengbatch.Mengtijd;
                            break;

                        case "T4 PROJECT>CAL CONNECTION>siroopPercentage":
                            waardeItem.Value = mengbatch.SiroopPercentage;
                            break;

                        case "T4 PROJECT>CAL CONNECTION>smaak":
                            switch (mengbatch.Smaak.Naam)
                            {
                                case "Lemon":
                                    waardeItem.Value = 3;
                                    break;

                                case "Sinas":
                                    waardeItem.Value = 2;
                                    break;

                                case "Cola":
                                    waardeItem.Value = 1;
                                    break;

                                default:
                                    break;
                            }

                            break;

                        case "T4 PROJECT>CAL CONNECTION>verwarmTijd":
                            waardeItem.Value = mengbatch.VerwarmTijd;
                            break;

                        default:
                            break;
                    }
                    valueList.Add(waardeItem);
                }
                group.AddItems(itemArray);
                for (int z = 0; z < valueList.Count; z++)
                {
                    valueList[z].ServerHandle = group.Items[z].ServerHandle;
                }
                group.Write(valueList.ToArray());
            }

            catch
            {
                DisconnectOPC();
                MessageBox.Show("Kan het niet weg schrijven", "error", MessageBoxButtons.OK);
            }
        }

        private void group_DataChanged(object subscriptionHandle, object requestHandle, ItemValueResult[] values)
        {
            if (itemInfoList.Count == 0)
            {
                foreach (ItemValueResult itemValue in values)
                {
                    itemInfoList.Add(new ItemInfo(itemValue.ItemName, itemValue.Value));
                }
            }
            else
            {
                for (int i = 0; i < values.Length - 1; i++)
                {
                    ItemInfo infoListInfo = itemInfoList.Where(temp1 => temp1.Name == values[i].ItemName).First();
                    if (values[i].Value != infoListInfo.ItemValue)
                    {
                        infoListInfo.ItemValue = values[i].Value;
                    }
                }
            }
        }

        private Opc.Da.Subscription MaakGroup(string name, int updaterate, bool active)
        {
            if (m_server.IsConnected == true && m_server.Subscriptions.Count == 0)
            {
                group = (Opc.Da.Subscription)m_server.CreateSubscription(new Opc.Da.SubscriptionState() { Name = name, Active = active, UpdateRate = updaterate });
                group.DataChanged += new Opc.Da.DataChangedEventHandler(group_DataChanged);
            }

            return group;
        }

        #endregion OPC

        #region Uitvoer

        public void Demo(Mengbatch mengbatch)
        {
            foreach (ItemInfo item in itemInfoList)
            {
                item.ProgramActiveTimer.Start();
            }
            totalTimeActive.Start();
            //WriteMengbatchToOPC(mengbatch);
            var list = new List<ItemInfo>();
            list.Add(new ItemInfo("T4 PROJECT>CAL CONNECTION>C#start", true));
            GeefVeranderingenDoorAanOPCItemInfo(list);
        }

        public void UitvoerenAlleOrders()
        {
            Order order = orderList.Where(orderItem => orderItem.Klaar == false).First();
            if (order != null)
            {
                Mengbatch batch = order.MengbatchList.Where(batchItem => batchItem.Klaar == false).First();
                if (batch != null)
                {
                    totalTimeActive.Start();
                    ItemInfo infoItemVullenBezig = itemInfoList.Where(item => item.Name == "Bezig").First();
                    ItemInfo infoItemMengenBezig = itemInfoList.Where(item => item.Name == "Bezig").First();
                    ItemInfo infoItemSpoelenBezig = itemInfoList.Where(item => item.Name == "Bezig").First();
                    if (Convert.ToBoolean(infoItemVullenBezig.ItemValue) != true)// als nog niet bezig , zoek een mengbatch om uit te voeren
                    {
                        if (KiesOptimaleDoeltank(order.MengbatchList.Where
                            (mengbatchItem => mengbatchItem.Klaar == false).First()) != null)
                        {
                            BehandelMengbatchInOpstelling(order.MengbatchList.Where(mengbatchItem => mengbatchItem.Klaar == false).First());
                        }
                        else
                        {
                            // juiste symbol voor spoelen vinden
                            ItemInfo temp = itemInfoList.Where(item => item.Name == "Spoelen").First();
                            GeefSpoelenDoor();
                            while (Convert.ToBoolean(temp.ItemValue) == false)
                            {
                            }
                        }
                    }
                    if (Convert.ToBoolean(infoItemMengenBezig.ItemValue) != true)
                    {
                    }
                }
            }
            //totalTimeActive.Stop();
        }

        public Doeltank KiesOptimaleDoeltank(Mengbatch mengbatch)
        {
            Doeltank newTank = null;
            if (mengbatch.Handmatig == false)
            {
                var query = (from doeltank in doelTanken
                             where mengbatch.Smaak == doeltank.HuidigeSmaak && doeltank.InGebruik == false
                             select doeltank).First()
                            ;
                newTank = query;
            }
            return newTank;
        }

        public void GeefSpoelenDoor()
        {
        }

        private void BehandelMengbatchInOpstelling(Mengbatch mengbatch)
        {
            // geef values van batch aan PLC doeltank etc
            foreach (Vulbatch vulbatch in mengbatch.VulbatchList)// wanneer klaar met mengbatch maken
            {
                // wachten tot PLC niet actief is
                // geef waardes door , aantal vaten etc
            }
            mengbatch.Klaar = true;
        }

        #endregion Uitvoer

        #region OEE

        private void timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (m_server.IsConnected == true)
            {
                Thread.Sleep(1000);
                mijnIO.WriteOEE(itemInfoList, totalTime, totalTimeActive);
            }
        }

        #endregion OEE
    }
}